parser grammar CParser;

options {
  language = Java;
  tokenVocab = CLexer;
  ASTLabelType = MiArbol;
  output = AST;
  backtrack = true;
}

tokens {
  INST_C;
  BLOQUE;
}

@header {
  package PL.practica10;
}

entrada: (sentencias_fichero)* -> ^(INST_C sentencias_fichero*)
       ;

// lo que aparece en el fichero
sentencias_fichero : var_dec 
                   | metodo
                   ;

metodo : (tipo | VOID^) ID ABRIR_PAR! CERRAR_PAR! bloque_llaves
       ;
       

bloque_llaves : ABRIR_LLAVE! instruccion+ CERRAR_LLAVE!
              ;

//  posibles reglas que pueden aparecer dentro de un if
others : var_dec
            | asignacion
            | fun_call 
            | sentencia_while
            | BREAK SEPARADOR!
            ;

// posibles reglas que pueden aparecer dentro de un bloque de llaves
// igual que la anterior pero con el if para evitar la recursividad por la izquierda
instruccion :  var_dec
            | asignacion
            | fun_call 
            | if_m_u
            | sentencia_while
            | if_aritmetico 
            | BREAK SEPARADOR!
            ;
           

var_dec : tipo ID (COMA ID)* SEPARADOR -> ^(tipo ID) ^(tipo ID)*
        ;
          
asignacion : ID ASIGNACION^ expr SEPARADOR!
           ;          
            
fun_call : ID ABRIR_PAR! CERRAR_PAR! SEPARADOR!
         ;  

// if resuelto con el problema del dangling else

if_m_u : match_if 
       | unmatch_if
       ;

match_if : sentencia_if match_if ELSE match_if
           | others
           ;
           
unmatch_if : sentencia_if if_m_u
           | sentencia_if match_if ELSE unmatch_if
           ; 
           
sentencia_if : IF^ ABRIR_PAR! condicion CERRAR_PAR! 
             ;           
     
// while
   
sentencia_while :  WHILE^ ABRIR_PAR! condicion CERRAR_PAR! (bloque_llaves | instruccion)
                ;

if_aritmetico : condicion INTERROGACION^ expr DOSPUNTOS! expr SEPARADOR!
              ;


// reglas de expresiones aritméticas

expr
  : expr_mult ((MAS^ | MENOS^) expr_mult)*
  ;

expr_mult
  : expr_base ((ASTERISCO^ | SLASH^) expr_base)*
  ;
  
expr_base
  : ABRIR_PAR! expr CERRAR_PAR!
  | CARACTER
  | ID
  | NUMERO
  ;

// condiciones

condicion : expr op_relacionales expr
          ;

// REGLAS para simplificar

tipo : INT^
     | CHAR^
     | FLOAT^
     ;

op_relacionales : MAYOR_IGUAL^
                | MAYOR^
                | MENOR_IGUAL^
                | MENOR^
                | DISTINTO^
                | IGUAL^
                ;
